package com.fuhailiu.opengl.utils;

import java.util.LinkedHashMap;

public class BenchmarkUtil {

	private static final String TAG = BenchmarkUtil.class.getSimpleName();

	private static LinkedHashMap<String, Long> mStartTimeMap = new LinkedHashMap<String, Long>();

	private static final int TOP_METHOD_LEVEL = 1;

	/**
	 * 在函数内部调用，同一个函数中，只能调用一次start，而且在start之后必须调用一次stop
	 */
	public synchronized static void start() {
		StackTraceElement[] stacks = new Throwable().getStackTrace();
		if (null != stacks && stacks.length > 0) {
			String className = stacks[TOP_METHOD_LEVEL].getClassName();
			String methodName = stacks[TOP_METHOD_LEVEL].getMethodName();
			mStartTimeMap.put(className + methodName, System.currentTimeMillis());
		}
	}

	/**
	 * 可以在任意位置调用，调用了start("xxx")方法，必须有对应的stop("xxx")方法
	 */
	public synchronized static void start(String label) {
		if (null == label) {
			LogUtil.LogE(TAG, "label cannot be NULL");
			return;
		}
		mStartTimeMap.put(label, System.currentTimeMillis());
	}

	/**
	 * 在函数内部调用，同一个函数中，只能调用一次start，而且在start之后必须调用一次stop
	 */
	public synchronized static void stop() {
		long endTime = System.currentTimeMillis();
		StackTraceElement[] stacks = new Throwable().getStackTrace();
		if (null != stacks && stacks.length > 0) {
			String className = stacks[TOP_METHOD_LEVEL].getClassName();
			String methodName = stacks[TOP_METHOD_LEVEL].getMethodName();
			String key = className + methodName;
			Long startTime = mStartTimeMap.get(key);
			if (null != startTime) {
				printLog(className, methodName, endTime - startTime.longValue());
				mStartTimeMap.remove(key);
			} else {
				LogUtil.LogE(TAG, "There is no match class and method, do you forgot to call start() ?");
			}
		}
	}

	/**
	 * 可以在任意位置调用，调用了start("xxx")方法，必须有对应的stop("xxx")方法
	 */
	public synchronized static void stop(String label) {
		if (null == label) {
			LogUtil.LogE(TAG, "label cannot be NULL");
			return;
		}
		long endTime = System.currentTimeMillis();
		Long startTime = mStartTimeMap.get(label);
		if (null != startTime) {
			String className = "";
			StackTraceElement[] stacks = new Throwable().getStackTrace();
			if (null != stacks && stacks.length > 0) {
				int level = TOP_METHOD_LEVEL;
				className = stacks[level].getClassName();
				while (className.contains(BenchmarkUtil.class.getName())) {
					className = stacks[++level].getClassName();
				}
			}
			printLog(className + "," + label, endTime - startTime.longValue());
			mStartTimeMap.remove(label);
		} else {
			LogUtil.LogE(TAG, "There is no match class and method, do you forgot to call start(label) ?");
		}
	}

	public static void reset() {
		if (null != mStartTimeMap) {
			mStartTimeMap.clear();
		}
	}

	private static void printLog(String className, String methodName, long time) {
		StringBuffer sb = new StringBuffer().append("	").append(className).append(".").append("[" + methodName + "]").append("	cost	").append(time).append("	ms");
		LogUtil.LogI(TAG, sb.toString());
	}

	private static void printLog(String str, long time) {
		StringBuffer sb = new StringBuffer().append("	").append(str).append("	cost	").append(time).append("	ms");
		LogUtil.LogI(TAG, sb.toString());
	}

}
